#!/sbin/sh

# SPDX-FileCopyrightText: 2022-2024 Andrew Gunnerson
# SPDX-License-Identifier: GPL-3.0-only

# 获取安装时传入的参数
OUTFD=${2}      # 输出文件描述符，用于向安装界面发送信息
ZIPFILE=${3}    # 安装包文件路径

# 设置默认umask值
umask 022

# 定义ui_print函数，用于在安装界面显示信息
ui_print() {
    printf "ui_print %s\nui_print\n" "${*}" > /proc/self/fd/"${OUTFD}"
}

# 判断是否通过recovery安装（检查是否存在recovery文件）
if [ -f /sbin/recovery ] || [ -f /system/bin/recovery ]; then
    # 通过recovery安装，启用严格模式
    set -exu

    ui_print 'Mounting system'  # 显示正在挂载system分区

    # 获取当前启动槽位（A/B分区设备）
    slot=$(getprop ro.boot.slot_suffix)

    # 根据设备类型设置system分区块设备路径
    if [[ -e /dev/block/mapper/system"${slot}" ]]; then
        ui_print "- Device uses dynamic partitions"  # 动态分区设备
        block_dev=/dev/block/mapper/system"${slot}"
        blockdev --setrw "${block_dev}"  # 设置块设备为读写模式
    elif [[ -e /dev/block/bootdevice/by-name/system"${slot}" ]]; then
        ui_print "- Device uses static partitions"   # 静态分区设备
        block_dev=/dev/block/bootdevice/by-name/system"${slot}"
    else
        ui_print "- System block device not found"   # 未找到system块设备
        exit 1
    fi

    ui_print "- System block device: ${block_dev}"   # 显示system块设备路径

    # 根据系统目录结构设置挂载点和根目录
    if [[ -d /mnt/system ]]; then
        mount_point=/mnt/system
        root_dir=${mount_point}
    elif [[ -d /system_root ]]; then
        mount_point=/system_root
        root_dir=${mount_point}
    else
        mount_point=/system
        # 判断是否使用system-as-root
        if [[ "$(getprop ro.build.system_root_image)" == true ]]; then
            root_dir=${mount_point}
        else
            root_dir=/
        fi
    fi

    ui_print "- System mount point: ${mount_point}"  # 显示system挂载点
    ui_print "- Root directory: ${root_dir}"         # 显示根目录路径

    # 挂载system分区为读写模式
    if mountpoint -q "${mount_point}"; then
        mount -o remount,rw "${mount_point}"
    else
        mount "${block_dev}" "${mount_point}"
    fi

    ui_print 'Extracting files'  # 显示正在解压文件

    # 获取模块ID（应用名称）
    # 注意：由于debug和release版本的apk文件名不同，不能简单覆盖
    app_id=$(unzip -p "${ZIPFILE}" module.prop | grep '^id=' | cut -d= -f2)

    # 删除旧版本应用目录（某些自定义recovery的rm命令在遇到ENOENT时可能不返回0）
    rm -rf "${root_dir}/system/priv-app/${app_id}" || :

    # 解压安装包中的system目录到系统目录
    unzip -o "${ZIPFILE}" 'system/*' -d "${root_dir}"

    ui_print 'Done!'  # 安装完成
else
    # 通过Magisk Manager安装

    # 导入Magisk工具函数
    . /data/adb/magisk/util_functions.sh

    # 定义检查overlayfs的函数
    has_overlays() {
        local mnt="${1}" count
        # 统计指定挂载点下overlay文件系统的数量
        count=$(awk -v mnt="${mnt}" '$9 == "overlay" && $5 ~ mnt' /proc/self/mountinfo | wc -l)
        [ "${count}" -gt 0 ]
    }

    # https://github.com/topjohnwu/Magisk/pull/6588
    # 检查Magisk版本是否满足要求（使用overlayfs的设备需要v26.0或更高版本）
    if [ -n "${MAGISK_VER_CODE}" ]; then
        ui_print "Magisk version: ${MAGISK_VER_CODE}"
        if has_overlays /system && [ "${MAGISK_VER_CODE}" -lt 26000 ]; then
            ui_print "Magisk v26.0 (26000) or newer is required because this device uses overlayfs"
            exit 1
        fi
    fi

    # 调用Magisk的模块安装函数
    install_module
fi